home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / c / flash-0.4.3.lha / flash-0.4.3 / Lib / button.cc < prev    next >
C/C++ Source or Header  |  1999-02-21  |  8KB  |  405 lines

  1. /////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998 Olivier Debon
  4. // 
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. // 
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. // 
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. // 
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //  
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <assert.h>
  26. #include "swf.h"
  27. #include "button.h"
  28. #include "graphic.h"
  29.  
  30. static char *rcsid = "$Id: button.cc,v 1.13 1999/02/14 21:59:28 olivier Exp $";
  31.  
  32. #define PRINT 0
  33.  
  34. #define Up        0x0
  35. #define Down        0x1
  36. #define Out        0x0
  37. #define Over        0x2
  38.  
  39. #define Idle        (Up  | Out)
  40. #define OutDown        (Out | Down)
  41. #define OverUp        (Over| Up)
  42. #define OverDown    (Over| Down)
  43.  
  44. static long old2current[] = {
  45.     /* Idle to Idle         */    0,
  46.     /* Idle to OutDown      */    0,
  47.     /* Idle to OverUp       */    1,
  48.     /* Idle to OverDown     */    128,
  49.     /* OutDown to Idle      */    64,
  50.     /* OutDown to OutDown   */    0,
  51.     /* OutDown to OverUp    */    0,
  52.     /* OutDown to OverDown  */    32,
  53.     /* OverUp to Idle       */    2,
  54.     /* OverUp to OutDown    */    0,
  55.     /* OverUp to OverUp     */    0,
  56.     /* OverUp to OverDown   */    4,
  57.     /* OverDown to Idle     */    256,
  58.     /* OverDown to OutDown  */    16,
  59.     /* OverDown to OverUp   */    8,
  60.     /* OverDown to OverDown */    0
  61. };
  62.  
  63. // Contructor
  64.  
  65. Button::Button(long id, int level) : Character(ButtonType, id)
  66. {
  67.     defLevel = level;
  68.     actionRecords = 0;
  69.     buttonRecords = 0;
  70.     conditionList = 0;
  71.     reset();
  72.     isMenu = 0;
  73.     sound[0] = sound[1] = sound[2] = sound[3] = 0;
  74. }
  75.  
  76. // Destructor
  77.  
  78. Button::~Button()
  79. {
  80.     if (actionRecords) {
  81.         ActionRecord *ar,*del;
  82.         for(ar = actionRecords; ar;) {
  83.             del = ar;
  84.             ar = ar->next;
  85.             delete del;
  86.         }
  87.     }
  88.     if (buttonRecords) {
  89.         ButtonRecord *br,*del;
  90.         for(br = buttonRecords; br;) {
  91.             del = br;
  92.             br = br->next;
  93.             if (del->cxform)
  94.                 delete del->cxform;
  95.             delete del;
  96.         }
  97.     }
  98.     if (conditionList) {
  99.         Condition *cond,*del;
  100.         for(cond = conditionList; cond;) {
  101.             ActionRecord *ar,*d;
  102.  
  103.             del = cond;
  104.             for(ar = cond->actions; ar;) {
  105.                 d = ar;
  106.                 ar = ar->next;
  107.                 delete d;
  108.             }
  109.  
  110.             cond = cond->next;
  111.             delete cond;
  112.         }
  113.     }
  114. }
  115.  
  116. ButtonRecord *
  117. Button::getButtonRecords()
  118. {
  119.     return buttonRecords;
  120. }
  121.  
  122. ActionRecord *
  123. Button::getActionRecords()
  124. {
  125.     return actionRecords;
  126. }
  127.  
  128. Sound **
  129. Button::getSounds()
  130. {
  131.     return sound;
  132. }
  133.  
  134. Condition *
  135. Button::getConditionList()
  136. {
  137.     return conditionList;
  138. }
  139.  
  140. void
  141. Button::setButtonSound(Sound *s, int state)
  142. {
  143.     if (state >=0 && state < 4) {
  144.         sound[state] = s;
  145.     }
  146. }
  147.  
  148. void
  149. Button::setButtonMenu(int menu)
  150. {
  151.     isMenu = menu;
  152. }
  153.  
  154. void
  155. Button::addButtonRecord( ButtonRecord *br )
  156. {
  157.     br->next = 0;
  158.  
  159.     if (buttonRecords == 0) {
  160.         buttonRecords = br;
  161.     } else {
  162.         ButtonRecord *current;
  163.  
  164.         for(current = buttonRecords; current->next; current = current->next);
  165.  
  166.         current->next = br;
  167.     }
  168. }
  169.  
  170. void
  171. Button::addCondition( long transition )
  172. {
  173.     Condition *condition;
  174.  
  175.     condition = new Condition;
  176.  
  177.     condition->transition = transition; 
  178.     condition->next = conditionList;
  179.  
  180.     // Move current actionRecords to this condition
  181.     condition->actions = actionRecords;
  182.     actionRecords = 0;
  183.  
  184.     conditionList = condition;
  185. }
  186.  
  187. void
  188. Button::addActionRecord( ActionRecord *ar )
  189. {
  190.     ar->next = 0;
  191.  
  192.     if (actionRecords == 0) {
  193.         actionRecords = ar;
  194.     } else {
  195.         ActionRecord *current;
  196.  
  197.         for(current = actionRecords; current->next; current = current->next);
  198.  
  199.         current->next = ar;
  200.     }
  201. }
  202.  
  203. void
  204. Button::getRegion(GraphicDevice *gd, Matrix *matrix, unsigned char id)
  205. {
  206.     ButtonRecord *br;
  207.  
  208.     for (br = buttonRecords; br; br = br->next)
  209.     {
  210.         if ((br->state & stateHitTest) && br->character /* Temporaire */) {
  211.             Matrix mat;
  212.  
  213.             mat = (*matrix) * br->buttonMatrix;
  214.             br->character->getRegion(gd, &mat, id);
  215.         }
  216.     }
  217. }
  218.  
  219. int
  220. Button::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform)
  221. {
  222.     ButtonRecord *br;
  223.     int sprite = 0;
  224.     Cxform *cxf = 0;
  225.  
  226. #if PRINT==2
  227.     printf("Rendering Button %d  for State(s) ", getTagId());
  228. #endif
  229.     for (br = buttonRecords; br; br = br->next)
  230.     {
  231.         if (br->state & renderState) {
  232.             Matrix mat;
  233.             
  234. #if PRINT==2
  235.         printf("%d ", br->state);
  236. #endif
  237.             mat = (*matrix) * br->buttonMatrix;
  238.             if (br->cxform) {
  239.                 cxf = br->cxform;
  240.             } else if (cxform) {
  241.                 cxf = cxform;
  242.             }
  243.             if (br->character->execute(gd, &mat, cxf)) {
  244.                 if (oldState != currentState) {
  245.                     br->character->reset();
  246.                 }
  247.                 sprite = 1;
  248.             }
  249.         }
  250.     }
  251. #if PRINT==2
  252.     printf("\n");
  253. #endif
  254.     return sprite;
  255. }
  256.  
  257. ActionRecord *
  258. Button::getActionFromTransition(ButtonState old)
  259. {
  260.     Condition *cond;
  261.     long mask, transition;
  262.  
  263.     if (old == currentState) return 0;
  264.  
  265.     // Build a fist transition mask
  266.     mask = Idle;
  267.     if (currentState & stateDown) {
  268.         mask |= Down;
  269.     }
  270.     if (currentState & stateUp) {
  271.         mask |= Up;
  272.     }
  273.     if (currentState & stateOver) {
  274.         mask |= Over;
  275.     } else {
  276.         mask |= Out;
  277.     }
  278.     if (old & stateDown) {
  279.         mask |= Down<<2;
  280.     }
  281.     if (old & stateUp) {
  282.         mask |= Up<<2;
  283.     }
  284.     if (old & stateOver) {
  285.         mask |= Over<<2;
  286.     } else {
  287.         mask |= Out<<2;
  288.     }
  289.  
  290.     transition = old2current[mask];
  291.  
  292.     for (cond = conditionList; cond; cond = cond->next) {
  293.         if (cond->transition & transition) {
  294.             return cond->actions;
  295.         }
  296.     }
  297.     return 0;
  298. }
  299.  
  300. ActionRecord *
  301. Button::eventHandler(GraphicDevice *gd, FlashEvent *event)
  302. {
  303.     oldState = currentState;
  304.  
  305.     static ActionRecord action;
  306.     static ActionRecord soundFx;
  307.  
  308.     action.action = ActionRefresh;
  309.     action.next = 0;
  310.  
  311.     soundFx.action = ActionPlaySound;
  312.     soundFx.next = &action;
  313.  
  314. #if PRINT==1
  315.     printf("Event Type = %d, Button %d  state = %d\n", event->type, getTagId(), currentState);
  316. #endif
  317.  
  318.     switch(event->type)
  319.     {
  320.         case FeButtonRelease:
  321.             if (currentState & stateOver) {
  322.                 if (currentState & stateDown) {
  323.                     // Action !!!
  324. #if PRINT
  325.                     printf("Action id %d %s!!!\n", getTagId(), sound[2] ? "(with sound)":"");
  326.                     printf("\n");
  327. #endif
  328.                     currentState = (ButtonState) (stateOver | stateUp);
  329.                     renderState = stateOver;
  330.  
  331.                     if (conditionList) {
  332.                         action.next = getActionFromTransition(oldState);
  333.                     } else {
  334.                         action.next = actionRecords;
  335.                     }
  336.  
  337.                     if (sound[0]) {
  338.                         soundFx.sound = sound[0];
  339.                         return &soundFx;
  340.                     } else {
  341.                         return &action;
  342.                     }
  343.                 } else {
  344.                     currentState = (ButtonState) (stateOver | stateUp);
  345.                 }
  346.             }
  347.             break;
  348.         case FeButtonPress:
  349.             if (currentState & stateOver) {
  350.                 currentState = (ButtonState) (currentState | stateDown);
  351.                 currentState = (ButtonState) (currentState & ~stateUp);
  352.                 renderState = stateDown;
  353.  
  354.                 if (conditionList) {
  355.                     action.next = getActionFromTransition(oldState);
  356.                 }
  357.  
  358.                 if (sound[2]) {
  359.                     soundFx.sound = sound[2];
  360.                     return &soundFx;
  361.                 } else {
  362.                     return &action;
  363.                 }
  364.             }
  365.             break;
  366.         case FeMouseMove:
  367.             if (gd->checkHitTest(getTagId(),event->x, event->y)) {
  368.                 currentState = (ButtonState)(currentState | stateOver);
  369.                 renderState = stateOver;
  370.             } else {
  371.                 currentState = stateUp;
  372.                 currentState = (ButtonState)(currentState & ~stateOver);
  373.                 renderState = stateUp;
  374.             }
  375.  
  376.             if (conditionList) {
  377.                 action.next = getActionFromTransition(oldState);
  378.             }
  379.  
  380.             if (oldState != currentState) {
  381.                 if (currentState & stateOver) {
  382.                     gd->setHandCursor(1);
  383.                     if (sound[1]) {
  384.                         soundFx.sound = sound[1];
  385.                         return &soundFx;
  386.                     }
  387.                 } else {
  388.                     gd->setHandCursor(0);
  389.                 }
  390.                 return &action;
  391.             }
  392.             break;
  393.     }
  394.  
  395.     return 0;
  396. }
  397.  
  398. void
  399. Button::reset()
  400. {
  401.     renderState = stateUp;
  402.     currentState = stateUp;
  403.     oldState = stateUp;
  404. }
  405.